/**
 * 存储迁移器
 *
 * 负责从LocalStorage迁移数据到IndexedDB
 */

import type { StorageResult } from '../types'
import { StorageErrorCode } from '../storageErrors'
import { AppDatabase } from '../indexedDB/database'
import { StoredDocument } from '../indexedDB/types'
import {
  MigrationSummary,
  ExportData,
  StoredContentEnvelope,
  MigrationConfig
} from './types'

/**
 * StorageMigrator - 数据迁移器类
 */
export class StorageMigrator {
  constructor(
    private db: AppDatabase,
    private config: MigrationConfig = {}
  ) {
    // 设置默认配置
    this.config = {
      clearLocalStorageAfterMigration: false,  // 默认不清理
      backupBeforeMigration: false,             // 默认不备份
      validateAfterMigration: true,             // 默认验证
      ...config
    }
  }

  /**
   * 执行完整的迁移流程
   */
  async migrate(): Promise<StorageResult<MigrationSummary>> {
    console.log('[迁移器] 开始数据迁移')

    try {
      // 1. 导出LocalStorage数据
      console.log('[迁移器] 步骤 1/5: 导出LocalStorage数据')
      const exportResult = await this.exportFromLocalStorage()
      if (!exportResult.ok) {
        return exportResult
      }

      const { documents, config } = exportResult.data
      console.log(`[迁移器] 导出完成: ${documents.length}个文档, ${Object.keys(config).length}个配置`)

      // 2. 验证数据完整性
      console.log('[迁移器] 步骤 2/5: 验证数据完整性')
      const validationResult = this.validateData(documents)
      if (!validationResult.ok) {
        return validationResult
      }
      console.log('[迁移器] 验证通过')

      // 3. 导入到IndexedDB
      console.log('[迁移器] 步骤 3/5: 导入数据到IndexedDB')
      const importResult = await this.importToIndexedDB(documents, config)
      if (!importResult.ok) {
        return importResult
      }
      console.log('[迁移器] 导入完成')

      // 4. 验证迁移结果
      if (this.config.validateAfterMigration) {
        console.log('[迁移器] 步骤 4/5: 验证迁移结果')
        const verifyResult = await this.verifyMigration(documents.length)
        if (!verifyResult.ok) {
          return verifyResult
        }
        console.log('[迁移器] 验证通过')
      }

      // 5. 标记迁移完成
      console.log('[迁移器] 步骤 5/5: 标记迁移完成')
      await this.markMigrationComplete()

      // 可选: 清理LocalStorage
      if (this.config.clearLocalStorageAfterMigration) {
        console.log('[迁移器] 清理LocalStorage数据')
        await this.cleanupLocalStorage()
      }

      const summary: MigrationSummary = {
        documentsCount: documents.length,
        configCount: Object.keys(config).length,
        success: true,
        migratedAt: new Date().toISOString()
      }

      console.log('[迁移器] ✅ 迁移完成', summary)
      return { ok: true, data: summary }
    } catch (error) {
      console.error('[迁移器] ❌ 迁移失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '数据迁移失败',
          cause: error
        }
      }
    }
  }

  /**
   * 从LocalStorage导出数据
   * 关键: 必须保留v1.0的所有字段
   */
  private async exportFromLocalStorage(): Promise<StorageResult<ExportData>> {
    const documents: StoredDocument[] = []
    const config: Record<string, any> = {}

    try {
      // 导出文档
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (!key || !key.startsWith('rmzf:content:')) {
          continue
        }

        const value = localStorage.getItem(key)
        if (!value) {
          continue
        }

        try {
          const envelope = JSON.parse(value) as StoredContentEnvelope

          // 关键: 直接从envelope.payload提取完整数据
          // 添加内部索引字段用于查询优化
          const doc: StoredDocument = {
            ...envelope.payload,  // 保留所有v1.0字段
            // 添加内部索引字段
            _searchTitle: envelope.payload.title.toLowerCase(),
            _updatedAtTimestamp: new Date(envelope.payload.updatedAt).getTime()
          }

          documents.push(doc)
          console.log(`[迁移器] 导出文档: ${doc.id} - ${doc.title}`)
        } catch (error) {
          console.warn(`[迁移器] 跳过无效数据: ${key}`, error)
        }
      }

      // 导出配置
      const aiConfigKey = 'rmzf:config:ai'
      const aiConfigValue = localStorage.getItem(aiConfigKey)
      if (aiConfigValue) {
        try {
          config.ai = JSON.parse(aiConfigValue)
          console.log('[迁移器] 导出AI配置')
        } catch (error) {
          console.warn('[迁移器] AI配置解析失败', error)
        }
      }

      return {
        ok: true,
        data: {
          documents,
          config,
          exportedAt: new Date().toISOString(),
          version: '1.0'
        }
      }
    } catch (error) {
      console.error('[迁移器] 导出失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: 'LocalStorage数据导出失败',
          cause: error
        }
      }
    }
  }

  /**
   * 验证数据完整性
   */
  private validateData(documents: StoredDocument[]): StorageResult<void> {
    console.log(`[迁移器] 验证${documents.length}个文档`)

    for (const doc of documents) {
      // 验证必需字段
      if (!doc.id) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: '文档缺少id字段',
            cause: doc
          }
        }
      }

      if (!doc.type) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `文档${doc.id}缺少type字段`,
            cause: doc
          }
        }
      }

      if (!doc.title) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `文档${doc.id}缺少title字段`,
            cause: doc
          }
        }
      }

      // 验证时间字段
      if (!doc.createdAt || !doc.updatedAt) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `文档${doc.id}缺少时间字段`,
            cause: doc
          }
        }
      }

      // 验证时间格式(应该是ISO字符串)
      if (typeof doc.createdAt !== 'string' || typeof doc.updatedAt !== 'string') {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `文档${doc.id}时间字段格式错误(应为ISO字符串)`,
            cause: doc
          }
        }
      }

      // 验证data字段存在(允许为空对象)
      if (doc.data === undefined || doc.data === null) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `文档${doc.id}缺少data字段`,
            cause: doc
          }
        }
      }
    }

    console.log('[迁移器] 所有文档验证通过')
    return { ok: true, data: undefined }
  }

  /**
   * 导入数据到IndexedDB
   */
  private async importToIndexedDB(
    documents: StoredDocument[],
    config: Record<string, any>
  ): Promise<StorageResult<void>> {
    try {
      console.log(`[迁移器] 导入${documents.length}个文档到IndexedDB`)

      // 批量导入文档
      if (documents.length > 0) {
        await this.db.documents.bulkAdd(documents)
        console.log(`[迁移器] ✅ ${documents.length}个文档已导入`)
      }

      // 导入配置
      for (const [key, value] of Object.entries(config)) {
        await this.db.config.put({
          key,
          value,
          updatedAt: Date.now()
        })
        console.log(`[迁移器] ✅ 配置已导入: ${key}`)
      }

      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[迁移器] 导入失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: 'IndexedDB数据导入失败',
          cause: error
        }
      }
    }
  }

  /**
   * 验证迁移结果
   */
  private async verifyMigration(expectedCount: number): Promise<StorageResult<void>> {
    try {
      const actualCount = await this.db.documents.count()

      if (actualCount !== expectedCount) {
        console.error(`[迁移器] ❌ 数量不匹配: 期望${expectedCount}, 实际${actualCount}`)
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: `迁移验证失败: 期望${expectedCount}个文档, 实际${actualCount}个`
          }
        }
      }

      console.log(`[迁移器] ✅ 验证通过: ${actualCount}个文档`)
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[迁移器] 验证失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '迁移结果验证失败',
          cause: error
        }
      }
    }
  }

  /**
   * 标记迁移完成
   */
  private async markMigrationComplete(): Promise<void> {
    localStorage.setItem('rmzf:meta:migrated', 'true')
    localStorage.setItem('rmzf:meta:migratedAt', new Date().toISOString())
    console.log('[迁移器] ✅ 迁移标记已设置')
  }

  /**
   * 清理LocalStorage(可选)
   * 仅清理文档数据,保留配置和迁移标记
   */
  private async cleanupLocalStorage(): Promise<void> {
    try {
      const keys = Object.keys(localStorage).filter(k => k.startsWith('rmzf:content:'))
      for (const key of keys) {
        localStorage.removeItem(key)
      }

      // 清理最近文档列表
      localStorage.removeItem('rmzf:recent:documents')

      console.log(`[迁移器] ✅ 已清理${keys.length}个LocalStorage条目`)
    } catch (error) {
      console.warn('[迁移器] 清理LocalStorage失败', error)
    }
  }

  /**
   * 检查是否需要迁移
   */
  static async checkMigrationNeeded(): Promise<boolean> {
    // 检查是否已迁移
    const migratedFlag = localStorage.getItem('rmzf:meta:migrated')
    if (migratedFlag === 'true') {
      console.log('[迁移器] 已完成迁移,无需重复执行')
      return false
    }

    // 检查是否有LocalStorage数据
    const keys = Object.keys(localStorage).filter(k => k.startsWith('rmzf:content:'))
    const needsMigration = keys.length > 0

    if (needsMigration) {
      console.log(`[迁移器] 检测到${keys.length}个文档需要迁移`)
    } else {
      console.log('[迁移器] 无需迁移')
    }

    return needsMigration
  }

  /**
   * 重置迁移标记(仅用于测试)
   */
  static resetMigrationFlag(): void {
    localStorage.removeItem('rmzf:meta:migrated')
    localStorage.removeItem('rmzf:meta:migratedAt')
    console.log('[迁移器] ⚠️ 迁移标记已重置')
  }
}
